﻿using System;
using System.Collections.Generic;

namespace _12306Bot.AuthCode
{
    //基本定义：
    //图片的像素的坐标表示为（高坐标值，宽坐标值）
    //宽坐标值代表列编号，高坐标值代表行编号
    /// <summary>
    /// 验证码基类
    /// </summary>
    public class AuthCharModule
    {
        /// <summary>
        /// 识别后字符
        /// </summary>
        private char _authChar;
        public char AuthChar
        {
            get { return _authChar; }
            set { _authChar = value; }
        }
        /// <summary>
        /// 图片二项化后的数组
        /// </summary>
        private int[,] _authCode;
        /// <summary>
        /// 行的总数
        /// </summary>
        public int RowCount
        {
            get { return _authCode.GetLength(0); }
        }
        /// <summary>
        /// 列的总数
        /// </summary>
        public int ColCount
        {
            get { return _authCode.GetLength(1); }
        }
        /// <summary>
        /// 以列为单位分组的List
        /// </summary>
        private List<uint> _authCodeColBit;
        /// <summary>
        /// 以列为单位分组的List
        /// </summary>
        public List<uint> AuthCodeColBit
        {
            get { return _authCodeColBit; }
            set { _authCodeColBit = value; }
        }
        /// <summary>
        /// 以行为单位分组的List
        /// </summary>
        private List<uint> _authCodeRowBit;
        /// <summary>
        /// 以行为单位分组的List
        /// </summary>
        public List<uint> AuthCodeRowBit
        {
            get { return _authCodeRowBit; }
            set { _authCodeRowBit = value; }
        }
        /// <summary>
        /// 错误像素的个数（旧算法用。用于存放，特征码和验证码的某个区域比较后，不一致像素最少的情况下，不一致的像素的个数）
        /// </summary>
        private int _missPixCount;
        /// <summary>
        /// 错误像素的个数
        /// </summary>
        public int MissPixCount
        {
            get { return _missPixCount; }
            set { _missPixCount = value; }
        }
        /// <summary>
        /// 前景像素个数，前景像素越多，匹配时越优先
        /// </summary>
        private int _pixCount;
        public int PixCount
        {
            get { return _pixCount; }
        }
        /// <summary>
        /// 构造函数，特征码
        /// </summary>
        /// <param name="authCharVal">识别后字符</param>
        /// <param name="authCodeVal">图片二项化数组</param>
        public AuthCharModule(char authCharVal, int[,] authCodeVal)
            : this(authCodeVal)
        {
            _authChar = authCharVal;
        }

        /// <summary>
        /// 构造函数，验证码
        /// </summary>
        /// <param name="authCodeVal">图片二项化数组</param>
        public AuthCharModule(int[,] authCodeVal)
        {
            setAuthCode(authCodeVal);
        }

        private void setAuthCode(int[,] authCodeVal)
        {
            _authCode = authCodeVal;
            //以行为分组进行扫描并设置List
            _authCodeRowBit = new List<uint>();
            _authCodeRowBit = getCodeRowBit(authCodeVal);

            //以列为分组进行扫描并设置List
            _authCodeColBit = new List<uint>();
            _authCodeColBit = getCodeColBit(authCodeVal);
        }

        /// <summary>
        /// 以行为分组对验证码进行分组，List
        /// </summary>
        /// <param name="authCodeVal">验证码二项化数组</param>
        /// <returns>返回的List</returns>
        private List<uint> getCodeColBit(int[,] authCodeVal)
        {
            List<uint> codeColBit = new List<uint>();
            for (int i = 0; i < authCodeVal.GetLength(1); i++)
            {
                codeColBit.Add(0);
                for (int j = 0; j < authCodeVal.GetLength(0); j++)
                {
                    //右边的是低位，左边的是高位
                    codeColBit[i] += Convert.ToUInt32(authCodeVal[j, i]) * (uint)Math.Pow(2, authCodeVal.GetLength(0) - 1 - j);
                    //计算特征码的像素总个数，同一坐标上如果有两个特征码都匹配，则像素数少的那个特征码被认为是不匹配的
                    if (authCodeVal[j, i] == HandleAuthChar.binPicCode.CodeOfPic)
                    {
                        this._pixCount++;
                    }
                }
            }
            return codeColBit;
        }

        /// <summary>
        /// 以列为分组对验证码进行分组，并返回List
        /// </summary>
        /// <param name="authCodeVal">验证码二项化数组</param>
        /// <returns>返回的List</returns>
        private List<uint> getCodeRowBit(int[,] authCodeVal)
        {
            List<uint> codeRowBit = new List<uint>();
            for (int i = 0; i < authCodeVal.GetLength(0); i++)
            {
                codeRowBit.Add(0);
                for (int j = 0; j < authCodeVal.GetLength(1); j++)
                {
                    //右边的是低位，左边的是高位
                    codeRowBit[i] += Convert.ToUInt32(authCodeVal[i, j].ToString()) * (uint)Math.Pow(2, authCodeVal.GetLength(1) - 1 - j);
                }
            }
            return codeRowBit;
        }
    }
}
